package com.hbk.base.component;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.hbk.base.common.CommonResult;
import com.hbk.base.common.RequestInfo;
import com.hbk.base.exception.NoTokenException;
import com.hbk.base.exception.TokenTimeoutException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.atomic.AtomicLong;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    private AtomicLong atomicLong = new AtomicLong(0);

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public CommonResult<?> bind(HttpServletRequest request, BindException e){

        log.error("参数绑定异常");
        BindingResult bindingResult = e.getBindingResult();
        String message = "";
        if(bindingResult.hasErrors()){
            FieldError fieldError = bindingResult.getFieldError();
            String field = fieldError.getField();
            String defaultMessage = fieldError.getDefaultMessage();
            StringBuffer sb = new StringBuffer();
            sb.append(field);
            sb.append(":");
            sb.append(defaultMessage);
            message = sb.toString();
        }
        CommonResult commonResult = new CommonResult();
        commonResult.setCode(1002);
        commonResult.setData(null);
        commonResult.setMsg(message);
        return errorResult(commonResult,e);
    }

    //请求中没有token
    @ResponseBody
    @ExceptionHandler(NoTokenException.class)
    public CommonResult<?> noTokenException(NoTokenException e){
        log.error("请求中没有token");
        CommonResult result = new CommonResult();
        result.setCode(2001);
        result.setMsg("当前接口需要登录用户访问");
        result.setData(null);
        return errorResult(result,e);
    }

    //token校验错误
    @ResponseBody
    @ExceptionHandler(JWTVerificationException.class)
    public CommonResult<?> jwtVerificationException(JWTVerificationException e){
        log.error("token校验失败");
        CommonResult result = new CommonResult();
        result.setCode(2006);
        result.setMsg("token校验失败");
        result.setData(null);
        return errorResult(result,e);
    }

    //用户登录超时
    @ResponseBody
    @ExceptionHandler(TokenTimeoutException.class)
    public CommonResult<?> tokenTimeoutException(TokenTimeoutException e){
        log.error("用户登录超时");
        CommonResult result = new CommonResult();
        result.setCode(2005);
        result.setMsg("用户登录超时");
        result.setData(null);
        return errorResult(result,e);
    }

    //所有的其他异常
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public CommonResult<?> exception(Exception e){

        long errorId = atomicLong.incrementAndGet();
        CommonResult result = new CommonResult();
        result.setMsg("服务器错误,错误编号为[#"+errorId+"],请联系管理人员.");
        result.setData(null);
        result.setCode(4001);
        return errorResult(result,e);
    }

    private CommonResult<?> errorResult(CommonResult<?> commonResult,Exception e){

        RequestInfo requestInfo = RequestInfo.get();
        StringBuilder stringBuilder = new StringBuilder();
        if(requestInfo!=null){
            stringBuilder.append(JSON.toJSONString(requestInfo));
            stringBuilder.append("\n");
        }
        stringBuilder.append(JSON.toJSONString(commonResult));
        stringBuilder.append("\n");
        stringBuilder.append("----------------------------\n");
        log.error(stringBuilder.toString());
        log.error(e.getMessage(),e);
        return commonResult;
    }
}
